package cn.buddha.jec.util;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author shihao
 * @description 模拟并发请求
 */
@Slf4j
public class TongHttpConcurrentUtil {

    public static void doSinglePost(String url, List<Map<String, Object>> paramListMap) {
        new TongHttpConcurrentUtil.UserRequest(Method.POST).doPost(url, paramListMap.get(0));
    }

    /**
     * 执行并发请求
     *
     * @param url          请求url
     * @param paramListMap 请求参数集合（集合的 size 就是 并发数）
     */
    public static void doConcurrentPost(String url, List<Map<String, Object>> paramListMap) {
        CountDownLatch cdl = new CountDownLatch(paramListMap.size());

        Stopwatch stopwatch = Stopwatch.createStarted();

        paramListMap.forEach(paramMap -> new Thread(new UserRequest(cdl, url, Method.POST, paramMap)).start());

        try {
            cdl.await();
        } catch (Exception e) {
            e.printStackTrace();
        }

        long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
        log.info("[{}]-Elapse, 总耗时: {} ms, 平均耗时: {} ms", Thread.currentThread().getId(),
                elapsed, new BigDecimal(elapsed).divide(new BigDecimal(paramListMap.size()), 3, RoundingMode.UP));
        stopwatch.stop();
    }

    public static class UserRequest implements Runnable {
        private CountDownLatch cdl;

        private String url;
        private Method requestMethod;
        private Map<String, Object> paramMap;

        public UserRequest(Method requestMethod) {
            this.requestMethod = requestMethod;
        }

        public UserRequest(CountDownLatch cdl, String url, Method requestMethod, Map<String, Object> paramMap) {
            this.cdl = cdl;
            this.url = url;
            this.requestMethod = requestMethod;
            this.paramMap = paramMap;
        }

        @Override
        public void run() {
            try {
                // 使用工具类发送http请求
                doPost(url, paramMap);
            } finally {
                cdl.countDown();
            }
        }

        /**
         * 这里可以根据自己的实际情况修改具体请求方式
         *
         * @param url
         * @param paramMap
         */
        public void doPost(String url, Map<String, Object> paramMap) {
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            System.out.println("请求地址:" + url);
            HttpRequest request = HttpUtil.createRequest(requestMethod, url);

            if (paramMap != null && !paramMap.isEmpty()) {
                String jsonString = JSON.toJSONString(paramMap);
                // json参数格式
                request.body(jsonString);
                // 表单请求
                // request.form(paramMap);

                System.out.println("请求参数:" + jsonString);
            }

            request.setConnectionTimeout(60 * 1000);
            String response = request.execute().body();
            System.out.println("响应结果:" + response);
        }
    }

}
